<?php

namespace Wgx\Admin\Controller;

use Wgx\Admin\Com\AdminMenuRightsUtil;
use Wgx\Admin\Com\Crud\Crud;
use Wgx\Admin\Com\Crud\CrudField;
use Wgx\Admin\Com\Crud\CrudUserInterface;
use Wgx\Admin\Com\Crud\EditPageInput\InputCheckboxGroup;
use Wgx\Admin\Com\Crud\EditPageInput\InputSelectOnline;
use Wgx\Admin\Com\Crud\InvalidFieldValueException;
use Wgx\Admin\Com\Crud\ListPageSearchInput\InputSelectOnline as LpSearchInputSelectOnline;
use Wgx\Admin\Entity\AdminMenuEntity;
use Wgx\Admin\Entity\AdminToMenuEntity;
use Wgx\Admin\Entity\AdminUserEntity;
use PhpYes\Apps;
use PhpYes\Entity\BaseEntity;
use Wgx\PdoEx\QueryBuilder;

class AdminToMenuController extends BaseController implements CrudUserInterface
{
    public function crud()
    {
        $crud = new Crud(AdminToMenuEntity::getSingle(), $this);

        $crud->addField(new CrudField('id', 'id', 'id', CrudField::ShowInAll))
            ->addField(new CrudField('adminId', '后台用户', '后台用户', CrudField::ShowInAll))
            ->addField(new CrudField('menuId', '后台菜单', '后台菜单', CrudField::ShowInAll))
            ->addField(new CrudField('rights', '权限', '用户拥有的对菜单操作的权限', CrudField::ShowInAll));

        $rights = AdminMenuRightsUtil::getSingleObj()->getCurrentRights();
        if ($rights && ($rights & (AdminToMenuEntity::RightRead | AdminToMenuEntity::RightUpdate | AdminToMenuEntity::RightDelete)) > 0) {
            $crud->addField(new CrudField('operate', '操作', '', CrudField::ShowInListPage));
        }

        return $crud->execute();
    }

    /**
     * @inheritDoc
     */
    public function setForOp(Crud $crud, $extra)
    {
        $op = $crud->getOp();
        $op = empty($op) ? '' : trim($op);
        if ($op == 'listpage') {
            $this->setForGetListPage($crud);
        } elseif ($op == 'editpage') {
            $this->setForGetEditPage($crud, empty($extra['entity']) ? null : $extra['entity']);
        }
    }

    public function setForGetListPage(Crud $crud)
    {
        $crud->setPageDisplayTarget(Crud::PageEditPage, 'layer', '800px', '400px');
        $crud->setPageDisplayTarget(Crud::PageReadPage, 'layer', '600px', '400px');

        // ---------- 列表页(listpage) searchbar
        $fieldName = 'adminId';
        /** @var CrudField $crudField */
        $crudField = $crud->getField($fieldName);
        $label = empty($crudField) ? '后台用户' : $crudField->getHName();
        $crud->addLpSearchField(
            $fieldName,
            new LpSearchInputSelectOnline(
                $label,
                '/adminuser/list',
                'name',
                '请选择' . $label,
                '10em',
                <<<'ITEMCONVERTER'
function (idx, item, arr) {
  item['text'] = '[' + (item['id'] || 0) + ']' + (item['name'] || '');
  return item;
}
ITEMCONVERTER
                ,
                20
            )
        );

        $fieldName = 'menuId';
        $crudField = $crud->getField($fieldName);
        $label = empty($crudField) ? '后台菜单' : $crudField->getHName();
        $crud->addLpSearchField(
            $fieldName,
            new LpSearchInputSelectOnline(
                $label,
                '/adminmenu/list',
                'name',
                '请选择' . $label,
                '18em',
                <<<'ITEMCONVERTER'
function (idx, item, arr) {
  item['text'] = '[' + (item['id'] || 0) + ']' + (item['name'] || '') + '(' + (item['level'] || 0) + '级)';
  return item;
}
ITEMCONVERTER
                ,
                20
            )
        );
        // ----------

        // ---------- 列表页(listpage) 表格的字段设置
        $crud->getField('id')->setLpWidth('20px')->setLpIsSortable(true)->setLpClassName('dt-center');
        $crud->getField('adminId')->setLpWidth('60px')->setLpIsSortable(true)->setLpRender(
            <<<'ADMINIDRENDER'
function xx(data, type, row, meta) {
return row.adminName || '';
}
ADMINIDRENDER
        )->setLpClassName('dt-center dt-body-left');
        $crud->getField('menuId')->setLpWidth('60px')->setLpIsSortable(true)->setLpRender(
            <<<'MENUIDRENDER'
function xx(data, type, row, meta) {
return row.menuName || '';
}
MENUIDRENDER
        )->setLpClassName('dt-center dt-body-left');
        $crud->getField('rights')->setLpWidth('60px')->setLpIsSortable(false)->setLpRender(
            <<<'RIGHTSRENDER'
function xx(data, type, row, meta) {
return row.rightNames || '';
}
RIGHTSRENDER
        )->setLpClassName('dt-center');

        $crudField = $crud->getField('operate');
        if ($crudField) {
            $render = CrudField::getLpOperateRender($crud);
            $crudField->setLpWidth('100px')->setLpIsSortable(false)->setLpRender($render);
        }

        // ---------- 列表页(listpage) 表格的初始默认排序
        $crud->setLpOrder('id', 'desc');
    }

    /**
     * @param Crud $crud
     * @param AdminToMenuEntity $entity
     */
    public function setForGetEditPage(Crud $crud, $entity)
    {
        $crud->addFile(Crud::PageEditPage, Crud::FileJsInline, \PhpYes\Apps::render()->getPage('admin/admin_to_menu_editpage.js.php'));

        $fieldName = 'adminId';
        $crudField = $crud->getField($fieldName);
        $adminId = intval($entity->getAdminId());
        $origValueHtml = '';
        if ($adminId) {
            $adminName = '';
            /** @var AdminUserEntity $adminUserEntity */
            $adminUserEntity = AdminUserEntity::getSingle()->selectById($adminId);
            if ($adminUserEntity) {
                $adminName = $adminUserEntity->getName();
            }
            $origValueHtml = "[{$adminId}]{$adminName}";
        }
        $crudField->setEpInputWidget(new InputSelectOnline(
                '/adminuser/list',
                'name',
                $adminId,
                $origValueHtml,
                true,
                '请选择' . $crudField->getHName(),
                '10em',
                <<<'ITEMCONVERTER'
function (idx, item, arr) {
item['text'] = '[' + (item['id'] || 0) + ']' + (item['name'] || '');
return item;
}
ITEMCONVERTER
                ,
                20
            )
        );

        $fieldName = 'menuId';
        $crudField = $crud->getField($fieldName);
        $menuId = intval($entity->getMenuId());
        $adminMenuEntity = null;
        $origValueHtml = '';
        if ($menuId) {
            /** @var AdminMenuEntity $adminMenuEntity */
            $adminMenuEntity = AdminMenuEntity::getSingle()->selectById($menuId);
            if ($adminMenuEntity) {
                $origValueHtml = '[' . $adminMenuEntity->getId() . ']' . $adminMenuEntity->getName() . '(' . $adminMenuEntity->getLevel() . '级)';
            }
        }
        $crudField->setEpInputWidget(new InputSelectOnline(
                '/adminmenu/list',
                'name',
                $menuId,
                $origValueHtml,
                true,
                '请选择' . $crudField->getHName(),
                '18em',
                <<<'ITEMCONVERTER'
function (idx, item, arr) {
  var id = item.id && parseInt(item.id) || 0;
  item['text'] = '[' + id + ']' + (item['name'] || '') + '(' + (item['level'] || 0) + '级)';
  if (idx < 1) {
    _page_data_['menuMap'] = {};
  }
  _page_data_['menuMap'][id] = item;
  return item;
}
ITEMCONVERTER
                ,
                20
            )
        );

        $fieldName = 'rights';
        $crudField = $crud->getField($fieldName);

        $rights = intval($entity->getRights());
        $rightArr = array();
        if ($rights) {
            $rr = array(
                AdminToMenuEntity::RightRead,
                AdminToMenuEntity::RightCreate,
                AdminToMenuEntity::RightUpdate,
                AdminToMenuEntity::RightDelete
            );
            foreach ($rr as $r) {
                if (($rights & $r) > 0) {
                    $rightArr[] = $r;
                }
            }
        }

        $map = array();
        if ($adminMenuEntity) {
            $mr = intval($adminMenuEntity->getRights());
            if ($mr) {
                $rr = array(
                    AdminToMenuEntity::RightRead,
                    AdminToMenuEntity::RightCreate,
                    AdminToMenuEntity::RightUpdate,
                    AdminToMenuEntity::RightDelete
                );
                foreach ($rr as $r) {
                    if (($mr & $r) > 0) {
                        $map[$r] = empty(AdminToMenuEntity::$rightMap[$r]) ? $r : AdminToMenuEntity::$rightMap[$r];
                    }
                }
            }
        }

        $crudField->setEpInputWidget(new InputCheckboxGroup($map, $rightArr, true));
    }

    /**
     * @inheritDoc
     */
    public function buildWhereForGetListData($params)
    {
        $where = array();
        $adminId = empty($params['adminId']) ? 0 : intval($params['adminId']);
        if ($adminId) {
            $where['admin_id'] = $adminId;
        }
        $menuId = empty($params['menuId']) ? 0 : intval($params['menuId']);
        if ($menuId) {
            $where['menu_id'] = $menuId;
        }

        return $where;
    }

    /**
     * @inheritDoc
     */
    public function buildOrderByForGetListData($fieldName, $direction)
    {
        $fieldName = empty($fieldName) ? null : trim($fieldName);
        if (empty($fieldName)) {
            return null;
        }
        $orderFieldMap = array(
            'id' => 'id',
            'adminId' => 'admin_id',
            'menuId' => 'menu_id',
            // 'rights' => 'rights',
        );
        $fieldName = empty($orderFieldMap[$fieldName]) ? null : $orderFieldMap[$fieldName];
        if (empty($fieldName)) {
            return null;
        }

        $direction = empty($direction) ? 0 : intval($direction);
        $direction = empty($direction) ? 'desc' : 'asc';
        return array($fieldName => $direction);
    }

    /**
     * @inheritDoc
     * @param AdminToMenuEntity $entity
     */
    public function formatData(Crud $crud, BaseEntity $entity, $context = null)
    {
        $op = $crud->getOp();
        $op = empty($op) ? '' : trim($op);
        if ($op == 'readpage') {
            $data = $entity->format(array(
                'admin_id' => 'adminId',
                'menu_id' => 'menuId'
            ));

            $data['rights'] = '[]';
            $rights = intval($entity->getRights());
            if ($rights) {
                $rightNames = [];
                $rr = array(
                    AdminToMenuEntity::RightRead,
                    AdminToMenuEntity::RightCreate,
                    AdminToMenuEntity::RightUpdate,
                    AdminToMenuEntity::RightDelete
                );
                foreach ($rr as $r) {
                    if (($rights & $r) > 0) {
                        $rightNames[] = AdminToMenuEntity::$rightMap[$r];
                    }
                }
                if ($rightNames) {
                    $data['rights'] = '[' . implode('，', $rightNames) . ']';
                }
            }
        } elseif ($op == 'editpage') {
            $data = $entity->format(array(
                'admin_id' => 'adminId',
                'menu_id' => 'menuId'
            ));
        } else {
            $data = $entity->format();
        }

        return $data;
    }

    /**
     * @inheritDoc
     */
    public function formatListData(Crud $crud, $data, $context = null)
    {
        if (empty($data)) {
            return null;
        }

        $op = $crud->getOp();
        $op = empty($op) ? '' : trim($op);
        $newDataList = array();
        if ($op == 'listdata') {
            $adminIds = array();
            $menuIds = array();
            foreach ($data as $item) {
                $adminIds[intval($item['admin_id'])] = 1;
                $menuIds[intval($item['menu_id'])] = 1;
            }
            $adminIds = array_keys($adminIds);
            $menuIds = array_keys($menuIds);

            $adminMap = array();
            $menuMap = array();

            $entityTpl = AdminUserEntity::getSingle();
            if (count($adminIds) > 1) {
                $qb = QueryBuilder::useDb($entityTpl->getConnName());
                $result = $qb->select($entityTpl->getTable(), '`id`, `name`', array('id' => array('in' => $adminIds)))->getPdoStatement()->fetchAll(\PDO::FETCH_ASSOC);
                if ($result) {
                    $adminMap = array_column($result, null, 'id');
                }
            } else {
                $result = $entityTpl->selectById($adminIds[0]);
                if ($result) {
                    $adminMap[$result->getId()] = $result->getData();
                }
            }

            $entityTpl = AdminMenuEntity::getSingle();
            if (count($menuIds) > 1) {
                $qb = QueryBuilder::useDb($entityTpl->getConnName());
                $result = $qb->select($entityTpl->getTable(), '`id`, `level`, `name`', array('id' => array('in' => $menuIds)))->getPdoStatement()->fetchAll(\PDO::FETCH_ASSOC);
                if ($result) {
                    $menuMap = array_column($result, null, 'id');
                }
            } else {
                $result = $entityTpl->selectById($menuIds[0]);
                if ($result) {
                    $menuMap[$result->getId()] = $result->getData();
                }
            }

            $formatMap = array(
                'admin_id' => 'adminId',
                'menu_id' => 'menuId',
            );
            foreach ($data as $item) {
                $entity = new AdminToMenuEntity($item);
                $newItem = $entity->format($formatMap);

                $adminId = intval($entity->getAdminId());
                $name = empty($adminMap[$adminId]['name']) ? '' : trim($adminMap[$adminId]['name']);
                $newItem['adminName'] = "[{$adminId}]{$name}";

                $menuId = intval($entity->getMenuId());
                $name = empty($menuMap[$menuId]['name']) ? '' : trim($menuMap[$menuId]['name']);
                $level = empty($menuMap[$menuId]['level']) ? 0 : intval($menuMap[$menuId]['level']);
                $newItem['menuName'] = "[{$menuId}]{$name}({$level}级)";

                $newItem['rightNames'] = '';
                $rights = intval($entity->getRights());
                if ($rights) {
                    $rightNames = [];
                    $rr = array(
                        AdminToMenuEntity::RightRead,
                        AdminToMenuEntity::RightCreate,
                        AdminToMenuEntity::RightUpdate,
                        AdminToMenuEntity::RightDelete
                    );
                    foreach ($rr as $r) {
                        if (($rights & $r) > 0) {
                            $rightNames[] = AdminToMenuEntity::$rightMap[$r];
                        }
                    }
                    if ($rightNames) {
                        $newItem['rightNames'] = implode('，', $rightNames);
                    }
                }

                $newDataList[] = $newItem;
            }
        } elseif ($op == 'export') {
            $formatMap = array(
                'admin_id' => 'adminId',
                'menu_id' => 'menuId',
            );
            foreach ($data as $item) {
                $entity = new AdminToMenuEntity($item);
                $newItem = $entity->format($formatMap);

                $newDataList[] = $newItem;
            }
        } else {
            foreach ($data as $item) {
                $entity = new AdminToMenuEntity($item);
                $newItem = $entity->format();
                $newDataList[] = $newItem;
            }
        }
        return $newDataList;
    }

    /**
     * @inheritDoc
     * @param AdminToMenuEntity $entity
     * @throws InvalidFieldValueException
     */
    public function createOrUpdate(Crud $crud, BaseEntity $entity, $data)
    {
        if (empty($data)) {
            return;
        }

        $op = $crud->getOp();
        $op = empty($op) ? '' : trim($op);
        if (empty($op)) {
            $fieldName = 'adminId';
            $fieldHName = $crud->getField($fieldName)->getHName();
            $adminId = empty($data[$fieldName]) ? 0 : intval($data[$fieldName]);
            if (empty($adminId)) {
                throw new InvalidFieldValueException($fieldName, '请传递' . $fieldHName);
            }
            $adminUserEntity = AdminUserEntity::getSingle()->selectById($adminId);
            if (empty($adminUserEntity)) {
                throw new InvalidFieldValueException($fieldName, '请传递有效的' . $fieldHName);
            }
            $entity->setAdminId($adminId);

            $fieldName = 'menuId';
            $fieldHName = $crud->getField($fieldName)->getHName();
            $menuId = empty($data[$fieldName]) ? 0 : intval($data[$fieldName]);
            if (empty($menuId)) {
                throw new InvalidFieldValueException($fieldName, '请传递' . $fieldHName);
            }
            $adminMenuEntity = AdminMenuEntity::getSingle()->selectById($menuId);
            if (empty($adminMenuEntity)) {
                throw new InvalidFieldValueException($fieldName, '请传递有效的' . $fieldHName);
            }
            $entity->setMenuId($menuId);

            $fieldName = 'rights';
            $fieldHName = $crud->getField($fieldName)->getHName();
            $fieldVal = empty($data[$fieldName]) ? null : $data[$fieldName];
            if (empty($fieldVal) || !is_array($fieldVal)) {
                throw new InvalidFieldValueException($fieldName, '请传递' . $fieldHName);
            }
            $rights = 0;
            foreach ($fieldVal as $r) {
                $r = empty($r) ? 0 : intval($r);
                if ($r && !empty(AdminToMenuEntity::$rightMap[$r])) {
                    $rights |= $r;
                }
            }
            if ($rights < 1) {
                throw new InvalidFieldValueException($fieldName, '请传递有效的' . $fieldHName);
            }
            $entity->setRights($rights);
        }
    }
}